import java.io.*
import kotlin.math.ceil

var itemLevel = 0
var emphStart = true
var boldStart = true
var inCodeBlock = false
var inTable = false
var inTabularx = false
fun main() {
    val path = ""
    val fileName = "we_party_deploy.md"
    val outFileName = "we_party_deploy_out.tex"
    val outFile = File(outFileName)
    val inputFile = File(fileName)
    if (!inputFile.exists()) {
        return
    }
    if (outFile.parentFile?.exists() == false) {
        outFile.parentFile.mkdirs()
    }
    if (!outFile.exists()) {
        outFile.createNewFile()
    }
    val reader = FileReader(inputFile)
    val writer = BufferedWriter(FileWriter(outFile))
    val lines = reader.readLines()
    lines.forEach {
        writer.write(parseMd(it))
        writer.newLine()
    }
    var result = ""
    while (itemLevel > 0) {
        itemLevel -= 1
        result += "\\end{itemize}" + "\n"
    }
    writer.write(result)
    writer.flush()
    writer.close()
    reader.close()
}

fun getItemizeEnd(): String {
    var result = ""
    while (itemLevel > 0) {
        itemLevel -= 1
        result += "\\end{itemize}" + "\n"
    }
    return result
}

fun parseMd(mdStr: String): String {
    var latexStr = ""
    var nowInTable = false
    //pre parse start
    //replace special character
    var mdStr1 = mdStr.replace("\u200B", "")
    if (!inCodeBlock) {
        mdStr1 = mdStr1.replace("{", "\\{")
                .replace("}", "\\}")
                .replace("&", "\\&")
                .replace("_", "\\_")
                .replace("$", "\\$")
    }
    //bold type
    while (mdStr1.contains("**")) {
        mdStr1 = if (boldStart) {
            mdStr1.replaceFirst("**", "\\textbf{")
        } else {
            mdStr1.replaceFirst("**", "}")
        }
        boldStart = !boldStart
    }
    //emph type
    while (mdStr1.contains("*")) {
        if (mdStr1[(mdStr1.indexOf('*') + 1)] == ' ') {
            break;
        }
        mdStr1 = if (emphStart) {
            mdStr1.replaceFirst("*", "\\emph{")
        } else {
            mdStr1.replaceFirst("*", "}")
        }
        emphStart = !emphStart
    }
    //pre parse end
    val trimmedAll = mdStr1.trim()
    val trimmedStart = mdStr1.trimStart()

    latexStr = if (trimmedAll.startsWith("######")) {
        // subparagraph
        "${getItemizeEnd()}\\subparagraph{${trimmedAll.substring(6).trim()}}~{}"

    } else if (trimmedAll.startsWith("#####")) {
        // paragraph
        "${getItemizeEnd()}\\paragraph{" + trimmedAll.substring(5).trim() + "}~{}"

    } else if (trimmedAll.startsWith("####")) {
        // subsubsection
        "${getItemizeEnd()}\\subsubsection{${trimmedAll.substring(4).trim()}}"

    } else if (trimmedAll.startsWith("###")) {
        // subsection
        "${getItemizeEnd()}\\subsection{${trimmedAll.substring(3).trim()}}"

    } else if (trimmedAll.startsWith("##")) {
        // section
        "${getItemizeEnd()}\\section{${trimmedAll.substring(2).trim()}}"
    } else if (trimmedAll.startsWith("#")) {
        "${getItemizeEnd()}\\chapter{${trimmedAll.substring(1).trim()}}"
    } else if (trimmedAll.startsWith("```") && !inCodeBlock) {
        // insert code block
        inCodeBlock = true
        "\\begin{lstlisting}"
    } else if (trimmedAll.startsWith("```") && inCodeBlock) {
        // finish code block
        inCodeBlock = false
        "\\end{lstlisting}"
    } else if (trimmedStart.startsWith("*") || trimmedStart.startsWith("-")) {
        // insert item
        var blankLength = 0
        for (c in mdStr1) {
            if (c == ' ') {
                blankLength += 1
            } else {
                break
            }
        }
        val currentItemLevel = blankLength / 2 + 1
//        println("itemLevel:$itemLevel")
//        println("currentItemLevel:$currentItemLevel")

        when {
            currentItemLevel > itemLevel -> {
                itemLevel += 1
                "\\begin{itemize}\n" +
                        "\\item " + trimmedStart.substring(1).trim()
            }
            currentItemLevel == itemLevel -> {
                "\\item " + trimmedStart.substring(1).trim()
            }
            else -> {
                itemLevel -= 1
                "\\end{itemize}" + "\n" + "\\item " + trimmedStart.substring(1).trim()
            }
        }
    } else if (trimmedStart.startsWith("![")) {
        //insert pic
        val startIndex = mdStr1.indexOf('(')
        val endIndex = mdStr1.indexOf(')')
        val picName = mdStr1.substring(startIndex + 1, endIndex)
        "\\begin{center}\n" +
                "    \\includegraphics[height=0.8\\textheight]{$picName}\n" +
                "\\end{center}"
    } else if (trimmedAll.startsWith("|") && trimmedAll.endsWith("|")) {
        var result = ""
        val items = trimmedAll.split("|").map {
            it.trim()
        }.filter {
            it != ""
        }
        if (trimmedAll.matches(Regex("""[- |]+"""))) {
            return ""
        }
        if (!inTable) {
            // insert table prefix
            inTable = true
            var tabular = ""
            if (items.size > 5) {
                //tabular
                //magic number 5
                inTabularx = false
                val ems = items.map {
                    var em = 0f
                    for (c in it) {

                        if (c.isDigit() || c.isUpperCase() || c.isLowerCase()) {
                            em += 0.5f
                            continue
                        }
                        em += if (c.isLetter()) {
                            1f
                        } else {
                            0.5f
                        }
                    }
                    "p{${ceil(em).toInt().coerceAtLeast(3)}em}"
                }
                tabular = ems.fold("|") { pre, next ->
                    "$pre$next|"
                }
                result +=
                        "\\begin{center}\n" +
                                "    \\resizebox{\\textwidth}{!}{\n" +
                                "        \\begin{tabular}{$tabular}\n" +
                                "            \\hline\n"
            } else {
                //tabularx
                inTabularx = true
                tabular = "|*{${items.size}}{X|}"
                result +=
                        "\\begin{center}\n" +
                                "        \\begin{tabularx}{\\textwidth}{$tabular}\n" +
                                "            \\hline\n"
            }


        }
        result += items.fold("") { pre, next ->
            "$pre& $next "
        }.drop(1)
        result += "\\\\\n" +
                "\\hline\n"

        nowInTable = true

        result
    } else {
        // 其他情况不进行命令转换
        mdStr1
    }

    if (inTable && !nowInTable) {
        // 表格结束

        val tableEnd = if (inTabularx) {
            " \\end{tabularx}\n" +
                    "\\end{center}\n"

        } else {
            " \\end{tabular}\n" +
                    "    }\n" +
                    "\\end{center}\n"

        }
        latexStr = tableEnd + latexStr
        inTable = false
    }
    return latexStr
}